// HSS.Forms.Docking.NestedPaneCollection.cs
// ----------------------------------------------------------------------------
// Licensed under the MIT license
// http://www.opensource.org/licenses/mit-license.html
// ----------------------------------------------------------------------------
// HighSpeed-Solutions, LLC
// Copyright (c) 2001-2010
// ----------------------------------------------------------------------------
// File:       NestedPaneCollection.cs
// Author:     HSS\gbanta
// Created:    08/12/2010
// Modified:   12/04/2010
// ----------------------------------------------------------------------------
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Drawing;

namespace HSS.Forms.Docking
{
	#region NestedPaneCollection
	/// <summary>
	/// NestedPaneCollection
	/// </summary>
	public sealed class NestedPaneCollection : ReadOnlyCollection<DockPane>
	{
		#region Fields

		private INestedPanesContainer _container;
		private VisibleNestedPaneCollection _visibleNestedPanes;

		#endregion

		#region Constructor
		/// <summary>
		/// ctor
		/// </summary>
		/// <param name="container">INestedPanesContainer</param>
		internal NestedPaneCollection(INestedPanesContainer container)
			: base(new List<DockPane>())
		{
			_container = container;
			_visibleNestedPanes = new VisibleNestedPaneCollection(this);
		}
		#endregion

		#region Properties

		/// <summary>
		/// Container
		/// </summary>
		public INestedPanesContainer Container
		{
			get { return _container; }
		}
		/// <summary>
		/// VisibleNestedPanes
		/// </summary>
		public VisibleNestedPaneCollection VisibleNestedPanes
		{
			get { return _visibleNestedPanes; }
		}
		/// <summary>
		/// DockState
		/// </summary>
		public DockState DockState
		{
			get { return Container.DockState; }
		}
		/// <summary>
		/// IsFloat
		/// </summary>
		public bool IsFloat
		{
			get { return DockState == DockState.Float; }
		}

		#endregion

		#region Methods

		/// <summary>
		/// GetDefaultPreviousPane
		/// </summary>
		/// <param name="pane">DockPane</param>
		/// <returns>DockPane</returns>
		public DockPane GetDefaultPreviousPane(DockPane pane)
		{
			for (int i = Count - 1; i >= 0; i--)
				if (this[i] != pane)
					return this[i];

			return null;
		}

		internal void Add(DockPane pane)
		{
			if (pane == null)
				return;

			NestedPaneCollection oldNestedPanes = (pane.NestedPanesContainer == null) ? null : pane.NestedPanesContainer.NestedPanes;
			if (oldNestedPanes != null)
				oldNestedPanes.InternalRemove(pane);
			Items.Add(pane);
			if (oldNestedPanes != null)
				oldNestedPanes.CheckFloatWindowDispose();
		}

		internal void Remove(DockPane pane)
		{
			InternalRemove(pane);
			CheckFloatWindowDispose();
		}

		private void InternalRemove(DockPane pane)
		{
			if (!Contains(pane))
				return;

			NestedDockingStatus statusPane = pane.NestedDockingStatus;
			DockPane lastNestedPane = null;
			for (int i = Count - 1; i > IndexOf(pane); i--)
			{
				if (this[i].NestedDockingStatus.PreviousPane == pane)
				{
					lastNestedPane = this[i];
					break;
				}
			}

			if (lastNestedPane != null)
			{
				int indexLastNestedPane = IndexOf(lastNestedPane);
				Items.Remove(lastNestedPane);
				Items[IndexOf(pane)] = lastNestedPane;
				NestedDockingStatus lastNestedDock = lastNestedPane.NestedDockingStatus;
				lastNestedDock.SetStatus(this, statusPane.PreviousPane, statusPane.Alignment, statusPane.Proportion);
				for (int i = indexLastNestedPane - 1; i > IndexOf(lastNestedPane); i--)
				{
					NestedDockingStatus status = this[i].NestedDockingStatus;
					if (status.PreviousPane == pane)
						status.SetStatus(this, lastNestedPane, status.Alignment, status.Proportion);
				}
			}
			else
				Items.Remove(pane);

			statusPane.SetStatus(null, null, DockAlignment.Left, 0.5);
			statusPane.SetDisplayingStatus(false, null, DockAlignment.Left, 0.5);
			statusPane.SetDisplayingBounds(Rectangle.Empty, Rectangle.Empty, Rectangle.Empty);
		}

		private void CheckFloatWindowDispose()
		{
			if (Count == 0 && Container.DockState == DockState.Float)
			{
				FloatWindow floatWindow = (FloatWindow)Container;
				if (!floatWindow.Disposing && !floatWindow.IsDisposed)
					NativeMethods.PostMessage(((FloatWindow)Container).Handle, FloatWindow.WM_CHECKDISPOSE, 0, 0);
			}
		}

		#endregion

	}
	#endregion
}